//! # 核心抽象和接口
//!
//! 这个模块包含认证授权系统的核心抽象和接口定义。
//! 大部分代码复用自 `rustcloud-gateway` 的认证模块，确保兼容性和一致性。

pub mod context;
pub mod principal;
pub mod resource;
pub mod errors;
pub mod traits;

// 重新导出核心类型
pub use context::AuthContext;
pub use principal::{Principal, PrincipalType};
pub use resource::Resource;
pub use errors::{AuthError, AuthResult};
pub use traits::{
    AuthProvider, AuthProviderType, 
    AuthenticationService, AuthorizationService,
    PermissionChecker, TokenProvider
};

#[cfg(test)]
mod tests {
    use super::*;
    use std::collections::HashMap;

    #[test]
    fn test_auth_context_creation() {
        let context = AuthContext::new(
            Default::default(),
            "POST".to_string(),
            "/api/login".to_string(),
            Some("192.168.1.100".to_string()),
        );
        
        assert_eq!(context.method, "POST");
        assert_eq!(context.uri, "/api/login");
        assert_eq!(context.remote_addr, Some("192.168.1.100".to_string()));
    }

    #[test]
    fn test_principal_creation() {
        let principal = Principal::new(
            "user123".to_string(),
            "John Doe".to_string(),
            PrincipalType::User,
        );
        
        assert_eq!(principal.id, "user123");
        assert_eq!(principal.name, "John Doe");
        assert_eq!(principal.principal_type, PrincipalType::User);
        assert!(principal.roles.is_empty());
        assert!(principal.permissions.is_empty());
    }

    #[test]
    fn test_resource_creation() {
        let resource = Resource::new(
            "user-service".to_string(),
            "/api/users".to_string(),
            "GET".to_string(),
        );
        
        assert_eq!(resource.service, "user-service");
        assert_eq!(resource.path, "/api/users");
        assert_eq!(resource.method, "GET");
    }

    #[test]
    fn test_principal_permissions() {
        let mut principal = Principal::new(
            "user123".to_string(),
            "John Doe".to_string(),
            PrincipalType::User,
        );
        
        principal = principal
            .add_role("admin".to_string())
            .add_permission("users:read".to_string())
            .add_permission("users:write".to_string());
        
        assert!(principal.has_role("admin"));
        assert!(principal.has_permission("users:read"));
        assert!(principal.has_permission("users:write"));
        assert!(!principal.has_permission("orders:read"));
    }

    #[test]
    fn test_auth_context_headers() {
        use axum::http::HeaderMap;
        
        let mut headers = HeaderMap::new();
        headers.insert("authorization", "Bearer token123".parse().unwrap());
        headers.insert("x-api-key", "key456".parse().unwrap());
        
        let context = AuthContext::new(
            headers,
            "GET".to_string(),
            "/api/data".to_string(),
            None,
        );
        
        assert_eq!(context.get_bearer_token(), Some("token123".to_string()));
        assert_eq!(context.get_api_key(), Some("key456"));
    }

    #[test]
    fn test_query_params() {
        let mut query_params = HashMap::new();
        query_params.insert("api_key".to_string(), "query_key789".to_string());
        
        let context = AuthContext::new(
            Default::default(),
            "GET".to_string(),
            "/api/data".to_string(),
            None,
        ).with_query_params(query_params);
        
        assert_eq!(context.get_api_key(), Some("query_key789"));
    }
}